﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using CoyoEden;
using System.Collections.Generic;
using CoyoEden.Models;

namespace Controls
{
	/// <summary>
	/// Build a CategoryTree-ul
	/// </summary>
	public class CategoryTree : Control
	{
		static CategoryTree()
		{
			Category.Saved += delegate { _Html = null; };

		}

		#region properties
		private List<Category> _Categories;
		/// <summary>
		/// Categories for building the tree.Should be assigned programatically
		/// </summary>
		public List<Category> Categories
		{
			get { return _Categories; }
			set {
				if (_Categories != value)
				{
					_Categories = value;
					_Html = null;
				}
			
			}
		}
		private string _CssClass;
		/// <summary>
		/// Css class
		/// </summary>
		public string CssClass
		{
			get { return string.IsNullOrEmpty(_CssClass) ? "" : _CssClass; }
			set { _CssClass = value; }
		}
		private static object _SyncRoot = new object();
		private static string _Html;
		private string Html
		{
			get
			{
				if (_Html == null)
				{
					lock (_SyncRoot)
					{
						if (_Html == null)
						{
							HtmlGenericControl ul = InitTree();
							System.IO.StringWriter sw = new System.IO.StringWriter();
							ul.RenderControl(new HtmlTextWriter(sw));
							_Html = sw.ToString();
						}
					}
				}

				return _Html;
			}
		}

		//Selectable tree properties
		private bool _Selectable;
		/// <summary>
		/// Selectable tree?
		/// </summary>
		public bool Selectable
		{
			get
			{
				return _Selectable;
			}
			set
			{
				if (_Selectable != value)
				{
					_Selectable = value;
					_Html = null;
				}
			}
		}
		private string _SelectedCategories;
		/// <summary>
		/// Selected Categories.Affects when Selectable=true.Seperated by "|" when multiple categories have been selected.
		/// </summary>
		public string SelectedCategories
		{
			get { return _SelectedCategories; }
			set
			{
				if (_SelectedCategories != value)
				{
					_SelectedCategories = value;
					_Html = null;
				}
			}
		}
		private List<string> _SelectedCategoryTitles;
		/// <summary>
		/// Category titles selected.
		/// </summary>
		public List<string> SelectedCategoryTitles {
			get {
				return _SelectedCategoryTitles;
			}
		}
		private string _SelectCallback;
		/// <summary>
		/// A javascript callback function.Handles category's select/click event 
		/// </summary>
		public string SelectCallback {
			get { return _SelectCallback; }
			set { _SelectCallback = value; }
		}
		#endregion

		#region helper methods
		private HtmlGenericControl InitTree()
		{
			HtmlGenericControl ul = new HtmlGenericControl("ul");
			ul.Attributes["class"] = _CssClass;
			ul.ID = this.ID;
			//Main tree content
			List<Control> lies = BuildCategoryTree();
			lies.ForEach(li => ul.Controls.Add(li));
			return ul;
		}
		private List<Control> BuildCategoryTree()
		{
			//build category menu according to settings
			List<Control> lies = new List<Control>();
			HtmlGenericControl li;
			if (Categories==null||Categories.Count==0)
			{
				li = new HtmlGenericControl("li");
				li.InnerHtml = "没有任何选定的分类";
				lies.Add(li);
				return lies;
			}
			//get all menus and submenus
			_SelectedCategoryTitles = new List<string>();
			Categories.OrderBy(item=>item.DisplayOrder).ToList().ForEach(delegate(Category c)
			{
				li = new HtmlGenericControl("li");
				li.Attributes["class"] = "";
				bool hasChild = CreateSubTree(li, c, true);
				lies.Add(li);
			});
			return lies;
		}

		private bool CreateSubTree(HtmlGenericControl li, Category c, bool topMenu)
		{
			bool hasChild = false;
			//get all sub categories
			List<Category> children = new List<Category>();
			children = Category.GetChildren(c);
			hasChild = (children.Count > 0);

			HtmlAnchor a = new HtmlAnchor();

			if (topMenu)
			{
				if (hasChild)
				{
					a.Attributes["class"] = "toplink notleaf";
				}
				else
				{
					a.Attributes["class"] = "toplink leaf";
				}

				HtmlGenericControl span = new HtmlGenericControl("span");
				span.InnerHtml = c.Title;
				a.Controls.Add(span);
			}
			else if (hasChild)
			{
				a.Attributes["class"] = "notleaf";
				a.Controls.Add(new LiteralControl(c.Title));
			}
			else
			{
				a.Attributes["class"] = "leaf";
				a.InnerHtml = c.Title;
			}
			a.HRef = Utils.RelativeWebRoot + "category/" + c.Id + PortalSettings.Instance.FileExtension;
			a.Title = "Category:" + c.Title;

			if (Selectable)
			{
				//checkbox wrapper
				HtmlGenericControl wrapper = new HtmlGenericControl("span");
				wrapper.Attributes["class"] = a.Attributes["class"];
		
				HtmlInputCheckBox cb = new HtmlInputCheckBox();
				cb.ID = "cb_GEN_" + c.Id.ToString();
				cb.Attributes["class"] = "cbcategory";
				cb.Value = c.Id.ToString();
				//click event's javascript callback
				if (!string.IsNullOrEmpty(SelectCallback)) {
					cb.Attributes["onclick"] = string.Format("{0}({1})",SelectCallback,"this");;
				}
				//whether checked?
				if (!string.IsNullOrEmpty(SelectedCategories))
				{
					var sCategories = SelectedCategories.Split('|');
					if(sCategories.ToList().Exists(item=>item==c.Id.ToString())){
						cb.Checked=true;
						_SelectedCategoryTitles.Add(c.Title);
					}
				}

				wrapper.Controls.Add(a);
				wrapper.Controls.Add(cb);

				li.Controls.Add(wrapper);
			}
			else {
				li.Controls.Add(a);
			}

			//parse children
			if (hasChild)
			{
				HtmlGenericControl ul = new HtmlGenericControl("ul");
				if (topMenu)
				{
					ul.Attributes["class"] = "sub";
				}

				foreach (Category c1 in children)
				{
					HtmlGenericControl li1 = new HtmlGenericControl("li");
					bool hasChild1 = CreateSubTree(li1, c1, false);
					ul.Controls.Add(li1);
				}
				li.Controls.Add(ul);
			}
			return hasChild;
		}
		#endregion

		/// <summary>
		/// render the control
		/// </summary>
		/// <param name="writer"></param>
		public override void RenderControl(HtmlTextWriter writer)
		{
			writer.Write(Html);
			writer.Write(Environment.NewLine);
		}
	}
}
